package org.example.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import lombok.extern.slf4j.Slf4j;
import org.example.mapper.DBConfigMapper;
import org.example.model.DbConfig;
import org.example.utils.CommonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Component
@Slf4j
public class DataSourceManager {

    private final ConcurrentMap<Long, WeakReference<Object>> dataSourceLocks =
            new ConcurrentHashMap<>();

    // 动态数据源Bean
    @Autowired
    private DynamicDataSource dynamicDataSource;

    @Autowired
    private DBConfigMapper dbConfigMapper;

    // 获取租户数据源（修复版）
    public void loadDataSource(Long subjectId) {

        String dsKey = CommonUtils.getDsKey(subjectId);

        // 第一步：无锁检查
        Map<Object, DataSource> resolvedDataSources = dynamicDataSource.getResolvedDataSources();

        DataSource ds = resolvedDataSources.get(dsKey);
        if (ds != null) {
            //todo  判断当前主题的数据源配置信息是否有变化，如果有变化则需要重新初始化数据源
            //1. 查询当前主题的数据源配置信息
            //2. 对比当前主题的数据源配置信息与缓存中的数据源配置信息
            //3. DruidAbstractDataSource druidAbstractDataSource = (DruidAbstractDataSource) ds;
            refreshDataSource(subjectId);

            //已初始化过，直接返回
            return;
        }

        // 同步代码块（主题粒度锁）
        synchronized (getSubjectLock(subjectId)) {
            // 双重检查锁
            if (resolvedDataSources.get(dsKey) == null) {
                // 查询数据库配置
                SubjectContext.setDataSourceKey(CommonUtils.getPrimaryDsKey());
                DbConfig dbconfig = dbConfigMapper.findBySubjectId(subjectId);
                // 创建新数据源
                ds = createDataSource(dbconfig);

                //注入路由器
                dynamicDataSource.addDataSource(dsKey, ds);
            }
        }
    }


    // 刷新数据源（修复版）
    public void refreshDataSource(Long subjectId) {
        Map<Object, DataSource> resolvedDataSources = dynamicDataSource.getResolvedDataSources();
        String dsKey = CommonUtils.getDsKey(subjectId);

        synchronized (getSubjectLock(subjectId)) {
            // 移除旧数据源
            DataSource oldDataSource = resolvedDataSources.remove(dsKey);
            if (oldDataSource != null) {
                // 安全关闭旧数据源
                if (oldDataSource instanceof DruidDataSource) {
                    ((DruidDataSource) oldDataSource).close();
                    //正在执行的连接是否有影响？？
                }
            }
            // 获取新配置
            SubjectContext.setDataSourceKey(CommonUtils.getPrimaryDsKey());
            DbConfig newConfig = dbConfigMapper.findBySubjectId(subjectId);
            if (newConfig == null) {
                log.error("数据源配置不存在，租户ID: {}", subjectId);
                return; // 配置不存在时提前返回
            }
            // 创建新数据源
            DataSource ds = createDataSource(newConfig);
            dynamicDataSource.addDataSource(dsKey, ds);

            log.info("租户 {} 数据源刷新完成", subjectId);
        }
    }


    // 动态创建Druid数据源
    private DataSource createDataSource(DbConfig config) {
        DruidDataSource ds = new DruidDataSource();
        ds.setUrl(config.getUrl());
        ds.setUsername(config.getUsername());
        ds.setPassword(config.getPassword());
        ds.setDriverClassName(config.getDriver());
        ds.setInitialSize(2);
        ds.setMinIdle(2);
        ds.setMaxActive(20);
        ds.setMaxWait(60000);
        ds.setValidationQuery("SELECT 1");
        ds.setTestWhileIdle(true);
        return ds;
    }

    private Object getSubjectLock(Long tenantId) {
        return dataSourceLocks.compute(tenantId, (key, ref) -> {
            Object lock = (ref != null) ? ref.get() : null;
            if (lock == null) {
                lock = new Object();
                return new WeakReference<>(lock);
            }
            return ref;
        }).get();
    }
}
